﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using DiscoveryLogic.UI.Layouts.Converters;
using DiscoveryLogic.UI.Layouts.Models;
using DiscoveryLogic.DataServices.DataSources;

namespace DiscoveryLogic.UI.Layouts.Controls
{
    public partial class EnrollmentFund : UserControl
    {
        #region Private Variables

            public static readonly int numFundTypes = 6;            
            public static readonly string[] fundColors = new string[6] { "#FFFFB135", "#FF4AB572", "#FFFF5F25", "#FF12574C", "#FF5D1E5D", "#FFC436BF" };

            private FundTypes fundType;
            private PieSlice parentSlice;

            private MouseManager mouseEventManager;

            private int numId;
            private string name;
            private double contributionPercent;
            private double fundValue;
            private bool panelMode = true;

            private bool iconMouseDown = false;

        #endregion

        #region Constructors

        /// <summary>
            /// Fund Constructor
            /// </summary>
            /// <param name="id">Unique id of the fund</param>
            /// <param name="fundType">Type of the fund</param>
            public EnrollmentFund(int id, FundTypes fundType)
            {
                // Required to initialize variables
                InitializeComponent();

                this.fundType = fundType;
                numId = id;
                
                // Set border color of fund icon based on fund type
                //FundIconOutline.SetValue(Rectangle.StrokeProperty, fundColors[(int)fundType]);
                StockIconOutline.SetValue(Rectangle.StrokeProperty, new SolidColorBrush(Utils.HexToColor(fundColors[(int)fundType])));

                switch ((int)FundType)
                {
                    case 0:
                        DomesticEquitiesFundIcon.Opacity = 1;
                        break;
                    case 1:
                        ForeignEquityFundIcon.Opacity = 1;
                        break;
                    case 2:
                        DomesticBondsFundIcon.Opacity = 1;
                        break;
                    case 3:
                        ForeignBondsFundIcon.Opacity = 1;
                        break;
                    case 4:
                        ShortTermFundIcon.Opacity = 1;
                        break;
                    case 5:
                        OtherFundIcon.Opacity = 1;
                        break;
                    default:
                        OtherFundIcon.Opacity = 1;
                        break;
                }


                // Create mouse event manager and attach handlers
                mouseEventManager = new MouseManager();

                EnrollmentFundCanvas.MouseLeftButtonDown += mouseEventManager.DragMouseDown;
                EnrollmentFundCanvas.MouseLeftButtonUp += mouseEventManager.DragMouseUp;
                EnrollmentFundCanvas.MouseMove += mouseEventManager.DragMouseMove;
                mouseEventManager.dragMove += new MouseManager.DragMoveEventHandler(OnDrag);
                mouseEventManager.dragMouseDown += new MouseManager.DragMouseDownEventHandler(OnDragMouseDown);
                mouseEventManager.dragMouseUp += new MouseManager.DragMouseUpEventHandler(OnDragMouseUp);
            }

            /// <summary>
            /// Fund Constructor
            /// </summary>
            /// <param name="id">Unique id of the fund</param>
            /// <param name="fundType">The type of fund</param>
            /// <param name="fundName">The name of the fund</param>
            /// <param name="fundValue">The dollar value of the fund</param>
            /// <param name="fundContribution">The percentage contributed to this fund</param>
            public EnrollmentFund(int id, FundTypes fundType, string fundName, double fundValue, double fundContribution)
                : this (id, fundType)
            {
                this.FundName = fundName;
                this.FundValue = fundValue;
                this.ContributionPercent = fundContribution;
            }

        #endregion

        #region Public Properties

            /// <summary>
            /// The type of fund this is
            /// </summary>
            public FundTypes FundType
            {
                get { return fundType; }
                set { fundType = value; }
            }

            /// <summary>
            /// The parent pie slice that this fund sits on.
            /// Can be null when fund is on a fund panel and
            /// not on a pie chart.
            /// </summary>
            public PieSlice ParentSlice
            {
                get { return parentSlice; }
                set { parentSlice = value; }
            }

            /// <summary>
            /// The unique id of the fund
            /// </summary>
            public int Id
            {
                get { return numId; }
                set { numId = value; }
            }

            /// <summary>
            /// The name of the fund.
            /// When the name is set, the fund name labels are also set.
            /// </summary>
            public String FundName
            {
                get { return name; }
                set 
                { 
                    name = value;
                    FundNameLabel.Text = name;
                    pieFundNameLabel.Text = name;
                }
            }

            /// <summary>
            /// Contribution percentage for this fund in point decimal form. eg. 0.75.
            /// When the contribution percent is set, the text label on the pie slice
            /// is set as well.
            /// </summary>
            public double ContributionPercent
            {
                get { return contributionPercent; }
                set
                {
                    contributionPercent = value;
                    pieFundContributionLabel.Text = "Contribution: " + Math.Round(100 * contributionPercent).ToString() + " %";
                                        
                    pieFundContributionLabel.Opacity = 1;                    
                }
            }

            /// <summary>
            /// Set the fund value. When the fund value is set, the text
            /// label is set as well.
            /// </summary>
            public double FundValue
            {
                get { return fundValue; }
                set
                {
                    fundValue = value;

                    if (fundValue < 1)
                    {
                        fundValue = Math.Round(fundValue, 2);
                    }
                    else
                    {
                        fundValue = Math.Round(fundValue);
                    }

                    pieFundValueLabel.Text = "Value:  " + fundValue.ToCurrency();
                }
            }
                    
        #endregion

        #region Public Methods

            /// <summary>
            /// Show or hide the fund value label.
            /// </summary>
            /// <param name="show"></param>
            public void HideFundValueLabel(bool hide)
            {
                if (hide)
                {
                    pieFundValueLabel.Opacity = 0;
                    pieFundContributionLabel.SetValue(Canvas.TopProperty, 10.0);
                }
                else
                {
                    pieFundValueLabel.Opacity = 1;
                    pieFundContributionLabel.SetValue(Canvas.TopProperty, 20.0);
                }
            }

            public void HideFundNameLabel(bool hide)
            {
                if (hide)
                {
                    pieFundNameLabel.Opacity = 0;
                }
                else
                {
                    pieFundNameLabel.Opacity = 1;
                }
            }

            /// <summary>
            /// Returns the fund color in hexidecimal format as a string
            /// </summary>
            /// <returns></returns>
            public string GetFundColor()
            {
                return fundColors[(int)fundType];
            }

            /// <summary>
            /// Sets the translation back to zero
            /// </summary>
            public void ResetPosition()
            {
                TranslateFund.X = 0;
                TranslateFund.Y = 0;
            }

            /// <summary>
            /// Switch to panel mode or pie mode.
            /// Changes the layout of the text labels.
            /// </summary>
            /// <param name="onPanelMode"></param>
            public void SwitchModes(bool onPanelMode)
            {
                panelMode = onPanelMode;

                if (panelMode == true)
                {
                    PieSliceTextCanvas.Visibility = Visibility.Collapsed;
                    FundTextCanvas.Visibility = Visibility.Visible;
                }
                else
                {
                    FundTextCanvas.Visibility = Visibility.Collapsed;
                    PieSliceTextCanvas.Visibility = Visibility.Visible;
                }
            }

            /// <summary>
            /// Set the text labels position to the left or right
            /// of the fund icon
            /// </summary>
            /// <param name="isOnRight"></param>
            public void SetPieTextPosition(bool isOnRight)
            {
                if (isOnRight == true)
                {
                    PieSliceTextCanvas.SetValue(Canvas.LeftProperty, 40.974);
                }
                else
                {
                    PieSliceTextCanvas.SetValue(Canvas.LeftProperty, -85.0);
                }
            }

            /// <summary>
            /// Call the shrink animation on the fund to shrink
            /// it to normal size (if enlarged).
            /// </summary>
            public void ShrinkIcon()
            {
                ShrinkAnimation.Begin();
            }

        #endregion

        #region Event Handlers

            /// <summary>
            /// On mouse enter, call the grow animation to enlarge
            /// the icon and text a bit.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            public void OnMouseEnter(object sender, EventArgs e)
            {
                if (panelMode == true)
                {
                    ShrinkAnimation.Stop();
                    GrowAnimation.Stop();
                    GrowAnimation.Begin();
                }
            }

            /// <summary>
            /// On mouse leave, call the shrink animation to shrink
            /// the icon and text back to normal.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            public void OnMouseLeave(object sender, EventArgs e)
            {
                if (panelMode == true)
                {
                    GrowAnimation.Stop();
                    ShrinkAnimation.Stop();
                    ShrinkAnimation.Begin();
                }
            }

            /// <summary>
            /// When the mouse is being dragged, move the fund
            /// along with it if it is in Panel Mode
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            /// <param name="mouseArgs"></param>
            private void OnDrag(object sender, DiscoveryLogic.UI.Layouts.Models.CustomEventArgs e, MouseEventArgs mouseArgs)
            {
                if (panelMode == true)
                {
                    TranslateFund.X = e.DragX;
                    TranslateFund.Y = e.DragY;

                    if (enrollmentFundDrag != null)
                    {
                        enrollmentFundDrag(this, mouseArgs);
                    }
                }
            }

            /// <summary>
            /// On mouse down, raise event enrollmentFundMouseDown.
            /// Handled in Enrollment.xaml.cs to change the parents of the fund.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void OnDragMouseDown(object sender, MouseEventArgs e)
            {
                if (enrollmentFundMouseDown != null && panelMode == true)
                {
                    enrollmentFundMouseDown(this, e);
                }
            }

            /// <summary>
            /// On mouse up, raisse event enrollmentFundMouseUp.
            /// Handled in Enrollment.xaml.cs to put the fund into the
            /// pie chart or to change the parents of the fund back to
            /// the fund panel.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void OnDragMouseUp(object sender, MouseEventArgs e)
            {
                if (enrollmentFundMouseUp != null && panelMode == true)
                {
                    enrollmentFundMouseUp(this, e);
                }
            }
        
        #endregion

        #region Events

            public event EventHandler enrollmentFundDrag;
            public event EventHandler enrollmentFundMouseDown;
            public event EventHandler enrollmentFundMouseUp;

        #endregion
    }
}
